﻿using PIMS.Base;
using PIMS.Commication.S7NetPlus;
using PIMS.DBModel;
using PIMS.Interface;
using PIMS.Models.Base;
using PIMS.ORM;
using PIMS.Util;
using PIMS.Utils;
using PIMS.XmlModel;
using PIMS.XmlModel.Snap7;
using PIMS_Interface.Base;
using PIMS_Interface.XmlModel.S7NETPlus;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;

namespace PIMS
{

    internal class Common
    {
        public static UserInfo UserLogin = new UserInfo();//当前登陆的用户
        public static readonly string ver = Assembly.GetExecutingAssembly().GetName().Version.ToString();
        public static IDebugMsg d = null;
        public static ILog4net log = new Log4NetHelper();
        private static Dictionary<String, String> stationDict = new Dictionary<string, string>();
        private static bool run = true;
        public static bool initPlcOK { set; get; }

        public static bool bSendPLC;// 是否已下发到产线

        /// <summary>
        /// 注册表路径
        /// </summary>
        public static readonly string regkeyPath = @"SOFTWARE\HBSPIMS";

        public static string basePath
        {
            get
            {
                return AppDomain.CurrentDomain.BaseDirectory;
            }            
        }
        public static PIMSConfigX pimsConfig = null;
        public static FeatureInfoX orderformcurrentConfigX = null;
        // public static FeatureInfoX featureInfoHistory = XmlHelper.XmlFileToObject<FeatureInfoX>(basePath + "Config/orderformhistoryConfig.xml");
        public static FeatureInfoX savedDataBagConfigX = null;
        public static FeatureInfoX savedDataConfigX = null;
        public static FeatureInfoX batchInfoSyncConfigX = null;


        public static AllPLC allPLC = new AllPLC();
        /*
           public static ICommunication[] weightPLC = null;
           public static ICommunication[] packerPLC = null;
           public static ICommunication[] palPLC = null;
           public static ICommunication[] labelPLC = null;
           public static ICommunication[] otherPLC = null;
         */

        /// <summary>
        /// 存储列名映射
        /// </summary>
        //public static Dictionary<string, string> workOrderColMapDict = new Dictionary<string, string>();

        private static Assembly assemWorkPlugin = null;

        /// <summary>
        /// 委托 用户改变
        /// </summary>
        public static Action<string> ActionUserChange;

        public static Dictionary<String, String> logGroupName = new Dictionary<string, string>();

        static Common()
        {
            try
            {
                if (pimsConfig == null)
                {
                    if (File.Exists(basePath + "Config/PIMSConfig.xml"))
                        pimsConfig = XmlHelper.XmlFileToObject<PIMSConfigX>(basePath + "Config/PIMSConfig.xml");
                    if (File.Exists(basePath + "Config/orderformcurrentConfig.xml"))
                        orderformcurrentConfigX = XmlHelper.XmlFileToObject<FeatureInfoX>(basePath + "Config/orderformcurrentConfig.xml");
                    if (File.Exists(basePath + "Config/savedDataBagConfig.xml"))
                        savedDataBagConfigX = XmlHelper.XmlFileToObject<FeatureInfoX>(basePath + "Config/savedDataBagConfig.xml");
                    if (File.Exists(basePath + "Config/savedDataConfig.xml"))
                        savedDataConfigX = XmlHelper.XmlFileToObject<FeatureInfoX>(basePath + "Config/savedDataConfig.xml");

                    batchInfoSyncConfigX = XmlHelper.XmlFileToObject<FeatureInfoX>(basePath + "Config/batchInfoSyncConfig.xml");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                log.Error("", ex);
            }
        }

        public static void InitPLC()
        {
            try
            {
                assemWorkPlugin = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + "Plugins\\PIMS_WorkPlugin.dll");

                string[] plcGroup = new string[] { "weight" , "packer" , "pal" , "label" , "other" };
                for(int i=0;i< plcGroup.Length;i++)
                {
                    XPLC x = pimsConfig.GetXPLCByKey(plcGroup[i]);    
                    if(x.count==0)
                    {
                        continue;
                    }
                    switch (plcGroup[i])
                    {
                        case "weight":
                            allPLC.weightPLC = new ICommunication[x.count];
                            logGroupName.Add(plcGroup[i], x.methodName);
                            break;
                        case "packer":
                            allPLC.packerPLC =new ICommunication[x.count];
                            logGroupName.Add(plcGroup[i], x.methodName);
                            break;
                        case "pal":
                            allPLC.palPLC =new ICommunication[x.count];
                            logGroupName.Add(plcGroup[i], x.methodName);
                            break;
                        case "label":
                            allPLC.labelPLC =new ICommunication[x.count];
                            logGroupName.Add(plcGroup[i], x.methodName);
                            break;
                        case "other":
                            allPLC.otherPLC =new ICommunication[x.count];
                            logGroupName.Add(plcGroup[i], x.methodName);
                            break;
                    }
                    switch (x.xModel)
                    {
                        case "Snap7XModel":
                            d.DebugMsg(String.Format("InitPLC -> {0} 不支持！", x.xModel), InfoLevel.warring);
                            break;
                        case "S7NETPlusXModel":
                            #region
                            for (int k = 0; k < x.count; k++)
                            {
                                string filename = x.value.Replace("1.", (k + 1).ToString() + ".");
                                string filePath = basePath + filename;
                                if (File.Exists(filePath))
                                {
                                    S7NETPlusXModel xConfig = XmlHelper.XmlFileToObject<S7NETPlusXModel>(filePath);
                                    ThreadPlcPara p = new ThreadPlcPara()
                                    {
                                        index = k,
                                        className = x.className,
                                        methodName = x.methodName
                                    };

                                    switch (plcGroup[i])
                                    {
                                        case "weight":
                                            allPLC.weightPLC[k] = new S7NetPlusHelper(xConfig);
                                            allPLC.weightPLC[k].xModel = xConfig;
                                            p.plc = allPLC.weightPLC[k];
                                            break;
                                        case "packer":
                                            allPLC.packerPLC[k] = new S7NetPlusHelper(xConfig);
                                            allPLC.packerPLC[k].xModel = xConfig;
                                            p.plc = allPLC.packerPLC[k];
                                            break;
                                        case "pal":
                                            allPLC.palPLC[k] = new S7NetPlusHelper(xConfig);
                                            allPLC.palPLC[k].xModel = xConfig;
                                            p.plc = allPLC.palPLC[k];
                                            break;
                                        case "label":
                                            allPLC.labelPLC[k] = new S7NetPlusHelper(xConfig);
                                            allPLC.labelPLC[k].xModel = xConfig;
                                            p.plc = allPLC.labelPLC[k];
                                            break;
                                        case "other":
                                            allPLC.otherPLC[k] = new S7NetPlusHelper(xConfig);
                                            allPLC.otherPLC[k].xModel = xConfig;
                                            p.plc = allPLC.otherPLC[k];
                                            break;
                                    }

                                    if (!String.IsNullOrEmpty(p.className) && p.plc != null)
                                    {
                                        new Thread(new ParameterizedThreadStart(Thread_WorkPLC)) { IsBackground = true }.Start(p);
                                    }
                                }
                                else
                                {
                                    d.DebugMsg(String.Format("{0} 不存在！", filePath), InfoLevel.warring);
                                }
                            }
                            #endregion
                            break;
                        default:
                            d.DebugMsg(String.Format("InitPLC -> {0} 不支持！", x.xModel), InfoLevel.warring);
                            break;
                    }
                }
                initPlcOK = true;
            }
            catch(Exception ex)
            {
                Common.log.Error("", ex);
                d.DebugMsg("InitPLC -> " + ex.Message,InfoLevel.error);
                MessageBox.Show(ex.StackTrace, "InitPLC()"+ ex.Message);
            }
        }

        private static void Thread_WorkPLC(Object obj)
        {
            ICommunication plc = null;
            int index = 0;

            object instance = null;
            MethodInfo miHandleCycle = null;

            string lastMessage = "";
            try
            {
                ThreadPlcPara para = (ThreadPlcPara)obj;
                plc = para.plc;
                index = para.index;

                //等待LOG窗口加载完成
                while (d == null)
                {
                    Thread.Sleep(1);
                }

                //利用反射机制将步骤名称与对应方法映射
                // Type t = typeof(fullClassName);
                // Assembly assem = typeof(Common).Assembly;               
                Type t = assemWorkPlugin.GetType(para.className);
                instance = Activator.CreateInstance(t);
                MethodInfo miInit = t.GetMethod("Init", BindingFlags.Instance | BindingFlags.Public);
                //miHandleCycle = t.GetMethod("HandleCycle", BindingFlags.Instance | BindingFlags.Public);
                miInit.Invoke(instance, new object[] { plc ,index, Common.d, Common.log,Common.pimsConfig});
            }
            catch (Exception ex)
            {
                Common.log.Error("", ex);
                d.DebugMsg(ex.Message, InfoLevel.error);
                return;
            }
        }

        public static void StopPLC()
        {
            run = false;

            if (allPLC.weightPLC !=null)
            {
                new Thread(new ParameterizedThreadStart(Thread_StopPLC)) { IsBackground = true }.Start(allPLC.weightPLC);
            }
            if (allPLC.packerPLC != null)
            {
                new Thread(new ParameterizedThreadStart(Thread_StopPLC)) { IsBackground = true }.Start(allPLC.packerPLC);
            }
            if (allPLC.palPLC != null)
            {
                new Thread(new ParameterizedThreadStart(Thread_StopPLC)) { IsBackground = true }.Start(allPLC.palPLC);
            }
            if (allPLC.labelPLC != null)
            {
                new Thread(new ParameterizedThreadStart(Thread_StopPLC)) { IsBackground = true }.Start(allPLC.labelPLC);
            }
            if (allPLC.otherPLC != null)
            {
                new Thread(new ParameterizedThreadStart(Thread_StopPLC)) { IsBackground = true }.Start(allPLC.otherPLC);
            }
        }

        private static void Thread_StopPLC(Object obj)
        {           
            try
            {
                ICommunication[] plc = (ICommunication[])obj;
                for(int i=0;i<plc.Length;i++)
                {
                    if (plc[i] != null)
                     plc[i].DisConnect();
                }
            }
            catch(Exception ex)
            {
                Common.log.Error("", ex);
            }
        }


        private static void InitStationDict(String configFile)
        {
            try
            {
                XmlDocUtil.LoadXmlDocumet(configFile);
                XmlNodeList nodePLC = XmlDocUtil.GetXmlNodeListByTagName("Station");
                XmlDocUtil.ReadFinish();
                foreach (XmlNode item in nodePLC[0].ChildNodes)
                {
                    stationDict.Add(item.Attributes["name"].Value, item.Attributes["value"].Value);
                }
            }
            catch (Exception ex)
            {
                d.DebugMsg("初始化StationConfig出错 " + ex.Message);
                Common.log.Error("", ex);
            }
        }

        public static void LabelPLCState(Label label, bool flag)
        {
            if (flag)
            {
                label.Text = "在线";
                label.ForeColor = Color.Black;
            }
            else
            {
                label.Text = "离线";
                label.ForeColor = Color.Red;
            }
        }

        /// <summary>
        /// 将当前的订单信息存储起来
        /// </summary>
        private static void SaveCurrentOrderForm(DataTable dtCurrent)
        {
            for(int i=0;i<dtCurrent.Rows.Count;i++)
            {
                try
                {
                    //orderformcurrent current = DatatableToEntity.FillModel<orderformcurrent>(dtCurrent.Rows[i], orderformcurrentConfigX);
                    orderformcurrent current = DatatableToEntity.FillModel<orderformcurrent>(dtCurrent.Rows[i]);
                    SqlSugarHelper.UpdateRecord<orderformcurrent>(current);
                }
                catch(Exception ex)
                {
                    Common.log.Error("", ex);
                    d.DebugMsg(ex.Message,InfoLevel.error);
                }
            }
        }

        public static void SaveCurrentOrderForm(DataGridView dataGridView)
        {
            DataTable dtCurrent = (DataTable)dataGridView.DataSource;
            SaveCurrentOrderForm(dtCurrent);
        }

        public static void SaveCurrentOrderToHistory(string workOrderNo)
        {
            orderformcurrent current = SqlSugarHelper.Query<orderformcurrent>(string.Format("workOrder = '{0}'",workOrderNo), "");
            orderformhistory history = new orderformhistory();
            EntityToEntity.EntityCopyToEntity(current, history);
            history.id = 0;
            history.line = current.id; //glb add
            history.finishTime = DateTime.Now;
            SqlSugarHelper.InsertRecord<orderformhistory>(history);
        }

    }


}
